﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using MvvmHelpers;
using System.Linq;
using System.Threading.Tasks;
using TabbedTemplate.Converters;
using TabbedTemplate.Models;
using TabbedTemplate.Services;

namespace TabbedTemplate.ViewModels
{
    /// <summary>
    /// 诗词收藏页ViewModel。
    /// </summary>
    public class FavoritePageViewModel : ViewModelBase
    {
        /******** 构造函数 ********/

        /// <summary>
        /// 收藏存储。
        /// </summary>
        private IFavoriteStorage _favoriteStorage;

        /// <summary>
        /// 诗词存储。
        /// </summary>
        private IStoreStorage _storeStorage;

        /// <summary>
        /// 内容导航服务。
        /// </summary>
        IPunchNavigationService _punchNavigationService;

        /// <summary>
        /// 诗词收藏页ViewModel。
        /// </summary>
        /// <param name="favoriteStorage">收藏存储。</param>
        /// <param name="storeStorage">诗词存储。</param>
        /// <param name="punchNavigationService">内容导航服务。</param>
        public FavoritePageViewModel(IFavoriteStorage favoriteStorage,
            IStoreStorage storeStorage,
            IPunchNavigationService punchNavigationService)
        {
            favoriteStorage.Updated += FavoriteStorageOnUpdated;
            _favoriteStorage = favoriteStorage;
            _storeStorage = storeStorage;
            _punchNavigationService = punchNavigationService;
            StoreFavoriteCollection =
                new ObservableRangeCollection<StoreFavorite>();
        }

        /******** 绑定属性 ********/

        /// <summary>
        /// 诗词收藏集合。
        /// </summary>
        private ObservableRangeCollection<StoreFavorite>
            _storeFavoriteCollection;

        public ObservableRangeCollection<StoreFavorite>
            StoreFavoriteCollection
        {
            get => _storeFavoriteCollection;
            set =>
                Set(nameof(StoreFavoriteCollection),
                    ref _storeFavoriteCollection, value);
        }

        /// <summary>
        /// 正在载入。
        /// </summary>
        public bool Loading
        {
            get => _loading;
            set => Set(nameof(Loading), ref _loading, value);
        }

        /// <summary>
        /// 正在载入。
        /// </summary>
        private bool _loading;

        /******** 绑定命令 ********/

        /// <summary>
        /// 页面显示命令。
        /// </summary>
        public RelayCommand PageAppearingCommand =>
            _pageAppearingCommand ?? (_pageAppearingCommand = new RelayCommand(
                async () => await PageAppearingCommandFunction()));

        /// <summary>
        /// 页面显示命令。
        /// </summary>
        private RelayCommand _pageAppearingCommand;

        public async Task PageAppearingCommandFunction()
        {
            if (_pageLoaded)
                return;

            lock (_pageLoadedLock)
            {
                if (_pageLoaded)
                    return;

                _pageLoaded = true;
            }


            Loading = true;
            StoreFavoriteCollection.Clear();
            var favoriteList = await _favoriteStorage.GetFavoritesAsync();

            StoreFavoriteCollection.AddRange(await Task.WhenAll(
                favoriteList.Select(async p =>
                    new StoreFavorite(
                        await _storeStorage.GetStoreByStoreUidAsync(p.StoreUid),
                        p, ConvertTimeStamp.ConvertTimeStampToDate(p.Timestamp)))));
            Loading = false;
        }

        /// <summary>
        /// 诗词点击命令。
        /// </summary>
        public RelayCommand<StoreFavorite> StoreTappedCommand =>
            _storeTappedCommand ??= new RelayCommand<StoreFavorite>(
                async storeFavorite =>
                    await StoreTappedCommandFunction(storeFavorite));

        /// <summary>
        /// 诗词点击命令。
        /// </summary>
        private RelayCommand<StoreFavorite> _storeTappedCommand;

        public async Task
            StoreTappedCommandFunction(StoreFavorite storeFavorite) =>
            await _punchNavigationService.NavigateToAsync(
                ContentNavigationConstant.StorePunchesPage,
                storeFavorite.Store);

        /******** 私有方法 ********/

        public async void FavoriteStorageOnUpdated(object sender,
            FavoriteStorageUpdatedEventArgs e)
        {
            var favorite = e.UpdatedFavorite;
            StoreFavoriteCollection.Remove(
                StoreFavoriteCollection.FirstOrDefault(p =>
                    p.Favorite.StoreUid == favorite.StoreUid));

            if (favorite.IsFavorite)
            {
                var storeFavorite = new StoreFavorite(
                    await _storeStorage.GetStoreByStoreUidAsync(favorite
                        .StoreUid), favorite,
                    ConvertTimeStamp
                        .ConvertTimeStampToDate(favorite.Timestamp));
                StoreFavoriteCollection.Insert(0, storeFavorite);
            }
        }

        /******** 私有变量 ********/

        /// <summary>
        /// 页面已加载。
        /// </summary>
        private volatile bool _pageLoaded;

        /// <summary>
        /// 页面已加载锁。
        /// </summary>
        private readonly object _pageLoadedLock = new object();
    }
}
